Telegram Group & Telegram Channel
⚙️ `[EnumeratorCancellation]` в C# — критически важный атрибут для корректной отмены в `IAsyncEnumerable`

В .NET асинхронные итераторы (`IAsyncEnumerable<T>`) стали мощным инструментом для потоковой обработки данных. Но если вы используете CancellationToken без специального атрибута [EnumeratorCancellation], ваш код может вести себя некорректно и утекать ресурсы. Разберёмся подробно.

⚠️ Проблема: токен есть, но он бесполезен

Допустим, вы пишете такой метод:


public async IAsyncEnumerable<string> FetchItems(CancellationToken cancellationToken)
{
foreach (var id in ids)
{
var item = await GetDataAsync(id);
yield return item;
}
}


Выглядит нормально, но есть подвох: при отмене токен не передаётся в `MoveNextAsync()`, то есть итерация может продолжаться, даже если вызвавшая сторона уже вызвала cancellationToken.Cancel().

💣 Последствия

• Фоновая загрузка продолжается после отмены
• Зависшие соединения, неосвобождённые ресурсы
• Непредсказуемое поведение в await foreach
• Сложные баги и плохая отзывчивость приложений

Решение: [EnumeratorCancellation]

Правильно будет вот так:


public async IAsyncEnumerable<string> FetchItems(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
await foreach (var item in LoadFromDb().WithCancellation(cancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
yield return item;
}
}


📌 Атрибут [EnumeratorCancellation] сообщает компилятору, что токен должен быть передан в реализацию `MoveNextAsync()` итератора. Без этого атрибута токен проигнорируется.

🧪 Как проверить


var cts = new CancellationTokenSource();
await foreach (var item in FetchItems(cts.Token))
{
if (item == "stop") cts.Cancel();
}


Если метод реализован без [EnumeratorCancellation], цикл может не остановиться.
Если с атрибутом — отмена сработает как положено, и итерация завершится немедленно.

🛠 Best Practices

Всегда используйте [EnumeratorCancellation], если метод IAsyncEnumerable<T> принимает CancellationToken
Внутри итератора:
- Вызывайте ThrowIfCancellationRequested()
- Оборачивайте вложенные await foreach или асинхронные методы в .WithCancellation(token)
Не используйте токен «для галочки» — он должен влиять на поведение итератора
Добавляйте юнит‑тесты на отмену, особенно если вы работаете с I/O, API или базами данных

📎 Заключение

Асинхронные итераторы — мощь. Но без [EnumeratorCancellation] ваш токен отмены просто не работает. И это не очевидно, пока вы не столкнётесь с багом, когда ресурсы не освобождаются, или цикл не завершается.

Одна строка — и вы защищены:


[EnumeratorCancellation] CancellationToken token


📚 Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html

🧠 Если ты пишешь на C# и используешь IAsyncEnumerable — знай: токен без атрибута = фейковая отмена.


📌 Читать

@csharp_1001_notes



tg-me.com/csharp_1001_notes/685
Create:
Last Update:

⚙️ `[EnumeratorCancellation]` в C# — критически важный атрибут для корректной отмены в `IAsyncEnumerable`

В .NET асинхронные итераторы (`IAsyncEnumerable<T>`) стали мощным инструментом для потоковой обработки данных. Но если вы используете CancellationToken без специального атрибута [EnumeratorCancellation], ваш код может вести себя некорректно и утекать ресурсы. Разберёмся подробно.

⚠️ Проблема: токен есть, но он бесполезен

Допустим, вы пишете такой метод:


public async IAsyncEnumerable<string> FetchItems(CancellationToken cancellationToken)
{
foreach (var id in ids)
{
var item = await GetDataAsync(id);
yield return item;
}
}


Выглядит нормально, но есть подвох: при отмене токен не передаётся в `MoveNextAsync()`, то есть итерация может продолжаться, даже если вызвавшая сторона уже вызвала cancellationToken.Cancel().

💣 Последствия

• Фоновая загрузка продолжается после отмены
• Зависшие соединения, неосвобождённые ресурсы
• Непредсказуемое поведение в await foreach
• Сложные баги и плохая отзывчивость приложений

Решение: [EnumeratorCancellation]

Правильно будет вот так:


public async IAsyncEnumerable<string> FetchItems(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
await foreach (var item in LoadFromDb().WithCancellation(cancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
yield return item;
}
}


📌 Атрибут [EnumeratorCancellation] сообщает компилятору, что токен должен быть передан в реализацию `MoveNextAsync()` итератора. Без этого атрибута токен проигнорируется.

🧪 Как проверить


var cts = new CancellationTokenSource();
await foreach (var item in FetchItems(cts.Token))
{
if (item == "stop") cts.Cancel();
}


Если метод реализован без [EnumeratorCancellation], цикл может не остановиться.
Если с атрибутом — отмена сработает как положено, и итерация завершится немедленно.

🛠 Best Practices

Всегда используйте [EnumeratorCancellation], если метод IAsyncEnumerable<T> принимает CancellationToken
Внутри итератора:
- Вызывайте ThrowIfCancellationRequested()
- Оборачивайте вложенные await foreach или асинхронные методы в .WithCancellation(token)
Не используйте токен «для галочки» — он должен влиять на поведение итератора
Добавляйте юнит‑тесты на отмену, особенно если вы работаете с I/O, API или базами данных

📎 Заключение

Асинхронные итераторы — мощь. Но без [EnumeratorCancellation] ваш токен отмены просто не работает. И это не очевидно, пока вы не столкнётесь с багом, когда ресурсы не освобождаются, или цикл не завершается.

Одна строка — и вы защищены:


[EnumeratorCancellation] CancellationToken token


📚 Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html

🧠 Если ты пишешь на C# и используешь IAsyncEnumerable — знай: токен без атрибута = фейковая отмена.


📌 Читать

@csharp_1001_notes

BY C# 1001 notes


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/csharp_1001_notes/685

View MORE
Open in Telegram


C 1001 notes Telegram | DID YOU KNOW?

Date: |

That growth environment will include rising inflation and interest rates. Those upward shifts naturally accompany healthy growth periods as the demand for resources, products and services rise. Importantly, the Federal Reserve has laid out the rationale for not interfering with that natural growth transition.It's not exactly a fad, but there is a widespread willingness to pay up for a growth story. Classic fundamental analysis takes a back seat. Even negative earnings are ignored. In fact, positive earnings seem to be a limiting measure, producing the question, "Is that all you've got?" The preference is a vision of untold riches when the exciting story plays out as expected.

Mr. Durov launched Telegram in late 2013 with his brother, Nikolai, just months before he was pushed out of VK, the Russian social-media platform he founded. Mr. Durov pitched his new app—funded with the proceeds from the VK sale—less as a business than as a way for people to send messages while avoiding government surveillance and censorship.

C 1001 notes from es


Telegram C# 1001 notes
FROM USA